package com.cqq.common.core.util;

import java.util.Collection;
import java.util.Map;

import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import com.cqq.common.core.base.BaseException;

/**
 * <h3>断言</h3>
 * 
 * <p>用于类方法被调用时检验参数的有效性</p>
 * <p>以抛异常形式定义结果</p>
 * 
 * @author GUOQIANG
 * @version 1.0.0
 */
public abstract class Assert {
	/**
	 * <h3>断言 表达式一定是true，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param expression 断言表达式
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void isTrue(boolean expression, E exception) throws E {
		if (!expression) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 对象一定是空，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param object 断言对象
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void isNull(Object object, E exception) throws E {
		if (object != null) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 对象一定不是空，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param object 断言对象
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void notNull(Object object, E exception) throws E {
		if (object == null) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 字符串长度一定大于0，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param text 断言字符串
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 * 
	 * @see org.springframework.util.StringUtils#hasLength(java.lang.CharSequence)
	 * <pre class="code">
	 * StringUtils.hasLength(null) = false
	 * StringUtils.hasLength("") = false
	 * StringUtils.hasLength(" ") = true
	 * StringUtils.hasLength("Hello") = true
	 * </pre>
	 */
	public static <E extends BaseException> void hasLength(String text, E exception) throws E {
		if (!StringUtils.hasLength(text)) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 字符串一定有内容，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param text 断言字符串
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 * 
	 * @see org.springframework.util.StringUtils#hasText(java.lang.CharSequence)
	 * <pre class="code">
	 * StringUtils.hasText(null) = false
	 * StringUtils.hasText("") = false
	 * StringUtils.hasText(" ") = false
	 * StringUtils.hasText("12345") = true
	 * StringUtils.hasText(" 12345 ") = true
	 * </pre>
	 */
	public static <E extends BaseException> void hasText(String text, E exception) throws E {
		if (!StringUtils.hasText(text)) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 字符串一定包含指定字符串，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param textToSearch 目标字符串
	 * @param substring 被匹配字符串
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void doesNotContain(String textToSearch, String substring, E exception) throws E {
		if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) && textToSearch.contains(substring)) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 数组不是空数组，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param array 断言数组
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void notEmpty(Object[] array, E exception) throws E {
		if (ObjectUtils.isEmpty(array)) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 数字不存在空元素，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param array 断言数组
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void noNullElements(Object[] array, E exception) throws E {
		if (array != null) {
			for (Object element : array) {
				if (element == null) {
					throw exception;
				}
			}
		}
	}

	/**
	 * <h3>断言 断言集合不是空集合，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param collection 断言表达式
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	@SuppressWarnings("rawtypes")
	public static <E extends BaseException> void notEmpty(Collection collection, E exception) throws E {
		if (CollectionUtils.isEmpty(collection)) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 断言Map不是空Map，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param map 断言map
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	@SuppressWarnings("rawtypes")
	public static <E extends BaseException> void notEmpty(Map map, E exception) throws E {
		if (CollectionUtils.isEmpty(map)) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 对象是指定的类型，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param type 断言类型
	 * @param obj 断言对象
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void isInstanceOf(Class<?> type, Object obj, E exception) throws E {
		if (type == null || !type.isInstance(obj)) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 两个类型是父子关系，否则抛出异常</h3>
	 * 
	 * @param <E> BaseException的实例类
	 * @param superType 父类型
	 * @param subType 子类型
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void isAssignable(Class<?> superType, Class<?> subType, E exception) throws E {
		if (subType == null || !superType.isAssignableFrom(subType)) {
			throw exception;
		}
	}

	/**
	 * <h3>断言 状态是真实的，否则抛出异常</h3>
	 * 
	 * <pre class="code">Assert.state(id == null, "The id property must not already be initialized");</pre>
	 * 
	 * @param <E> BaseException的实例类
	 * @param expression 状态结果
	 * @param exception 断言失败指定的异常
	 * @throws E 抛出指定异常
	 */
	public static <E extends BaseException> void state(boolean expression, E exception) throws E {
		if (!expression) {
			throw exception;
		}
	}
}